#include <linux/clocksource.h>

#include "../inc/tick.h"

/**
 * tick_program_event - program the CPU local timer device for the next event
 */
int tick_program_event(ktime_t expires, int force)
{
    struct clock_event_device *dev = this_clock_event();

    if (unlikely(expires == KTIME_MAX))
    {
        /*
         * We don't need the clock event device any more, stop it.
         */
        clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED);
        dev->next_event = KTIME_MAX;
        return 0;
    }

    if (unlikely(clockevent_state_oneshot_stopped(dev)))
    {
        /*
         * We need the clock event again, configure it in ONESHOT mode
         * before using it.
         */
        clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
    }

    return clockevents_program_event(dev, expires, force);
}

/**
 * tick_switch_to_oneshot - switch to oneshot mode
 */
int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
{
    struct clock_event_device *dev = this_clock_event();
    int ret = 0;

    if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT))
    {
        ret = -EINVAL;
    }
    else
    {
        dev->event_handler = handler;
        clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
    }

    return ret;
}
